using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DrawTools.Editor;
using DrawTools.Editor.CanvasFigures;
using DrawTools.Editor.Tools.States;

namespace DrawTools.Tools
{
  /// <summary>
  ///   Pointer tool
  /// </summary>
  public class PointerTool : Tool
  {
    private IPointerToolState _state;

    /// <summary>
    ///   Left mouse button is pressed
    /// </summary>
    /// <param name="canvas"></param>
    /// <param name="e"></param>
    public override void OnMouseDown(IDrawingCanvas canvas, MouseEventArgs e)
    {
      _state = null;
      Point point = e.Location;

      // Test for resizing (only if control is selected, cursor is on the handle)
      foreach (CanvasObject selectionedObject in canvas.GraphicsList.SelectedObjects)
      {
        int handleNumber = selectionedObject.HitTest(point);

        if (handleNumber > 0)
        {
          // keep resized object in class members
          _state = new ResizeObjectState(canvas, selectionedObject, handleNumber);
          break;
        }
      }

      // Test for move (cursor is on the object)
      if (_state == null)
      {
        CanvasObject canvasObject = canvas.GraphicsList.GetObjectAtPoint(point, false);

        if (canvasObject != null)
        {
          _state = new MoveObjectState(canvas, canvasObject, point);
        }
      }

      // Crop selection
      if (_state == null && canvas.Crop != null)
      {
        int cropHandle = canvas.Crop.HitTest(point);

        if (cropHandle >= 0)
        {
          _state = new CropSelectionState(canvas, cropHandle, point);
        }
      }

      // Net selection
      if (_state == null)
      {
        _state = new NetSelectionState(canvas, point);
      }

      canvas.CaptureMouse = true;
      canvas.Refresh();
    }

    /// <summary>
    ///   Mouse is moved.
    ///   None button is pressed, ot left button is pressed.
    /// </summary>
    /// <param name="canvas"></param>
    /// <param name="e"></param>
    public override void OnMouseMove(IDrawingCanvas canvas, MouseEventArgs e)
    {
      var point = new Point(e.X, e.Y);

      // set cursor when mouse button is not pressed
      if (e.Button == MouseButtons.None)
      {
        var cursor = GetHoverCursor(canvas, point);
        canvas.SetCursor(cursor);

        return;
      }

      if (e.Button != MouseButtons.Left)
        return;

      if (_state != null)
        _state.Update(point);
    }

    private static Cursor GetHoverCursor(IDrawingCanvas canvas, Point point)
    {
      Cursor cursor = null;

      foreach (var drawObject in canvas.GraphicsList)
      {
        cursor = GetObjectCursor(drawObject, point);

        if (cursor != null)
          break;
      }

      if (cursor == null && canvas.Crop != null)
        cursor = GetObjectCursor(canvas.Crop, point);

      return cursor ?? Cursors.Default;
    }

    private static Cursor GetObjectCursor(CanvasObject canvasObject, Point point)
    {
      int handleNumber = canvasObject.HitTest(point);

      if (handleNumber > 0)
        return canvasObject.GetHandleCursor(handleNumber);

      if (handleNumber == 0)
        return Cursors.Hand;

      return null;
    }

    /// <summary>
    ///   Right mouse button is released
    /// </summary>
    /// <param name="canvas"></param>
    /// <param name="e"></param>
    public override void OnMouseUp(IDrawingCanvas canvas, MouseEventArgs e)
    {
      _state.Release();
      _state = null;

      canvas.CaptureMouse = false;
      canvas.Refresh();
    }
  }
}